package cn.com.wantools.service.provider;

import cn.com.wantools.model.exchange.ExchangeInfo;
import cn.com.wantools.model.exchange.ExchangeQueryConfigInfo;
import cn.com.wantools.model.exchange.UcExchangeQueryConfig;
import cn.com.wantools.service.ExchangeService;
import cn.com.wantools.service.UcExchangeQueryConfigService;
import cn.com.wantools.service.UcExchangeRateService;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.jfinal.aop.Inject;
import com.jfinal.kit.LogKit;
import io.jboot.aop.annotation.Bean;

import java.math.BigDecimal;
import java.util.*;

@Bean
public class ExchangeServiceProvider implements ExchangeService {

    @Inject
    private UcExchangeRateService ucExchangeRateService;

    @Inject
    private UcExchangeQueryConfigService ucExchangeQueryConfigService;

    private final TimedCache<String, ExchangeInfo> timedCache = CacheUtil.newTimedCache(1000 * 60 * 60 * 25);
    private final TimedCache<String, ExchangeQueryConfigInfo> configCache = CacheUtil.newTimedCache(1000 * 60 * 60 * 24 * 7); //生效日期7天

    @Override
    public BigDecimal queryExchangeRate(String baseCurrency, String currency) {
        ExchangeInfo exchangeInfo =  timedCache.get(baseCurrency, false);
        if (exchangeInfo != null) {
            if (exchangeInfo.getExchange(currency) != null) {
                return exchangeInfo.getExchange(currency);
            }
        }

        exchangeInfo = loadExchangeRemote(baseCurrency);
        return exchangeInfo.getExchange(currency);
    }

    @Override
    public void reloadExchange () {
        LogKit.warn("reloadExchange");
        List<String> initCurrency = Arrays.asList(
                "CNY",
                "USD",
                "JPY",
                "EUR",
                "GBP",
                "CHF",
                "CAD",
                "AUD",
                "HKD",
                "IDR",
                "MYR",
                "NZD",
                "PHP",
                "SGD",
                "KRW",
                "THB");
        for (String baseCurrency: initCurrency) {
            ExchangeInfo exchangeInfo =  timedCache.get(baseCurrency, false);
            if (exchangeInfo != null && exchangeInfo.getExpiredTimestamp() != null && exchangeInfo.getExpiredTimestamp().compareTo(new Date().getTime()) < 0) {
                loadExchangeRemote(baseCurrency);
            } else if (exchangeInfo == null) {
                loadExchangeRemote(baseCurrency);
            }
        }

        //加载没有在基础汇率表中的
        for (ExchangeInfo item : timedCache) {
            if (!initCurrency.contains(item.getBaseCurrency())) {
                if (item.getExpiredTimestamp() != null && item.getExpiredTimestamp().compareTo(new Date().getTime()) < 0) {
                    loadExchangeRemote(item.getBaseCurrency());
                }
            }
        }
    }

    private ExchangeInfo loadExchangeRemote(String baseCurrency) {
        LogKit.warn("loadExchangeRemote, baseCurrency " + baseCurrency);
        //如果数据库中能获取到，则不再去远程请求
        ExchangeInfo exchangeInfo = queryExchangeInfo(baseCurrency);
        if (exchangeInfo != null) {
            timedCache.put(baseCurrency, exchangeInfo);
            return exchangeInfo;
        }

        if (configCache.isEmpty()) {
            loadExchangeQueryConfig();
        }
        if(configCache.isEmpty()) {
            LogKit.warn("exchange rate config is empty!!!");
            return null;
        }

        for (ExchangeQueryConfigInfo exchangeQueryConfigInfo : configCache) {
            String urlPattern = exchangeQueryConfigInfo.getUrlPattern();
            urlPattern = urlPattern.replace("{appKey}", exchangeQueryConfigInfo.getAppKey());
            urlPattern = urlPattern.replace("{appSecret}", exchangeQueryConfigInfo.getAppSecret());
            urlPattern = urlPattern.replace("{baseCurrency}", baseCurrency);
            //String responseString= HttpUtil.get("https://v6.exchangerate-api.com/v6/c9ec8f0e6757a493f94f05d4/latest/" + baseCurrency);
            String responseString = HttpUtil.get(urlPattern);
            JSONObject jsonObject = JSONUtil.parseObj(responseString);
            try {
                exchangeInfo = new ExchangeInfo();
                exchangeInfo.setBaseCurrency(baseCurrency);
                exchangeInfo.setExpiredTimestamp(jsonObject.getLong("time_next_update_unix") * 1000);
                JSONObject exchangeObj = jsonObject.getJSONObject("conversion_rates");
                for (Map.Entry e : exchangeObj.entrySet()) {
                    exchangeInfo.putExchange(String.valueOf(e.getKey()), BigDecimal.valueOf(Double.parseDouble(String.valueOf(e.getValue()))));
                }
                timedCache.put(baseCurrency, exchangeInfo);
                saveExchangeRate(exchangeInfo);
                break;
            } catch (Exception e) {
                LogKit.error("query exchange rate error!, baseExchange: " + baseCurrency);
            }
        }

        return timedCache.get(baseCurrency);
    }

    /**
     * 加载获取汇率服务的配置文件
     */
    private void loadExchangeQueryConfig() {
        List<ExchangeQueryConfigInfo> configList = ucExchangeQueryConfigService.loadExchangeQueryConfig();
        for (ExchangeQueryConfigInfo config : configList) {
            configCache.put(String.valueOf(config.getId()), config);
        }
    }

    /**
     * 保存汇率
     * @param exchangeInfo 汇率信息
     */
    private void saveExchangeRate(ExchangeInfo exchangeInfo) {
        ucExchangeRateService.saveExchangeRate(exchangeInfo);
    }

    /**
     * 若能获取到，则汇率，否则 返回null
     * @param baseCurrency 基础币种
     * @return ExchangeInfo
     */
    private ExchangeInfo queryExchangeInfo(String baseCurrency) {
        return ucExchangeRateService.queryByBaseCurrency(baseCurrency);
    }

}
